﻿using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Text;
using Nemerle.Utility;
using Nemerle.Macros;

using System;
using System.Collections.Generic;
using System.Linq;

using PEG = Nemerle.Peg;

namespace Nemerle2.Parser
{
  [Nemerle.MacroUsage(Nemerle.MacroPhase.WithTypedMembers, Nemerle.MacroTargets.Class)]
  macro PegParserProxy(tb : TypeBuilder, key : string)
  {
    try
    {
      def grammar = PegParserProxyMarshaller.Receive(tb.Manager, key) :> PEG.Grammar;
      PEG.GrammarImpl.MakeParser(ImplicitCTX(), tb, grammar);
    }
    catch
    {
      | e is PEG.GrammarException =>
        def loc = if (e.Location != Location.Default) e.Location else tb.Location;
        Message.Error(loc,  e.Message);
      | _ is PEG.CriticalUnexpectedException => ()
      | e is Exception =>
        assert2(false, e.ToString());
        Message.Error(tb.Location,  $"Exception $e");
    }
  }

  module PegParserProxyMarshaller
  {
    public Pass(manager : ManagerClass, data : object) : string
    {
      def token = Guid.NewGuid();
      manager.UserData[token] = data;
      token.ToString()
    }

    public Receive(manager : ManagerClass, key : string) : object
    {
      manager.UserData[Guid(key)]
    }
  }
}
